package cn.yudao.ymcc.service.impl;

import cn.yudao.GlobleException;
import cn.yudao.ymcc.constant.SmsCodeConstant;
import cn.yudao.ymcc.constant.SmsConstant;
import cn.yudao.ymcc.domain.MessageSms;
import cn.yudao.ymcc.dto.RedisSmsDto;
import cn.yudao.ymcc.dto.SmsCodeDTO;
import cn.yudao.ymcc.mapper.MessageBlacklistMapper;
import cn.yudao.ymcc.mapper.MessageSmsMapper;
import cn.yudao.ymcc.result.JSONResult;
import cn.yudao.ymcc.service.IVerifyCodeService;
import cn.yudao.ymcc.utils.AssertUtil;
import cn.yudao.ymcc.utils.StrUtils;
import cn.yudao.ymcc.utils.VerifyCodeUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private MessageSmsMapper messageSmsMapper;


    @Autowired
    private MessageBlacklistMapper blacklistMapper;

    @Override
    public JSONResult sendSmsCode(SmsCodeDTO dto) {
        // 判断是否被拉黑
        AssertUtil.isTrue(extracted(dto),"该电话已被拉黑");
        // 校验图形验证码是否相同
        AssertUtil.isTrue(checkImagCode(dto), SmsConstant.CHECK_IMAGCODE_EQ);
        // 获取短信验证码
        RedisSmsDto smsCode = getSmsCode(dto);
        // 发送手机验证码
        sendPhone(dto.getMobile(),smsCode.getCode());
        // 保存到数据库
        insertMessageSmsDB(smsCode,dto.getMobile());
        // 保存到redis中，并设置3分钟有效
        redisTemplate.opsForValue().set(SmsCodeConstant.SMS_PHONE + dto.getMobile(), smsCode, SmsConstant.PHONE_KEY_TIME, TimeUnit.MINUTES);
        return JSONResult.success();
    }

    /**
    * @Title: extracted
    * @Description: 判断用户是否被拉黑
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/8 11:09
    * @Parameters:
    * @Return
    */
    public boolean extracted(SmsCodeDTO dto) {
        // 查询黑名单表中是否有messageSms 根据电话号作为唯一标识查询
        EntityWrapper entityWrapper = new EntityWrapper();
        entityWrapper.eq("phone", dto.getMobile());
        List list = blacklistMapper.selectList(entityWrapper);
        if (list == null || list.size() > 0){
            return false;
        }
        return true;
    }

    /**
    * @Title: getImgBase
    * @Description: 生成图形验证码
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/6 21:59
    * @Parameters:
    * @Return
    */
    @Override
    public String getImgBase(String imageCodeKey) {
        // 判断传入的值是否为null
        if (imageCodeKey == null && "".equals(imageCodeKey)) {
            throw new GlobleException(SmsConstant.GLOBLE_EXCEPTION_CODE);
        }
        // 获取到随机的4位的字符串通过StrUtils的方法获取
        String complexRandomString = StrUtils.getComplexRandomString(4);
        // 将传入的uuid作为key，随机的4位字符串作为value，存储到redis中
        redisTemplate.opsForValue().set(imageCodeKey, complexRandomString, SmsConstant.IMAGE_KEY_TIME, TimeUnit.MINUTES);
        // 使用VerifyCodeUtils工具类将字符串添加到一个随机图片中去，并生成Base64的编码字符串
        String baseImg = VerifyCodeUtils.VerifyCode(100, 30, complexRandomString);
        return baseImg;
    }

    /**
    * @Title: insertMessageSmsDB
    * @Description: 将数据保存到数据库中
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/6 21:53
    * @Parameters:
    * @Return
    */
    public void insertMessageSmsDB(RedisSmsDto smsCode,String phone){
        // 保存到数据库
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("用户注册");
        messageSms.setContent("您的验证码为 "+ smsCode.getCode() +" ,请在 10 分钟内使用");
        messageSms.setSendTime(new Date());
        // 获取到id
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        String ip = requestAttributes.getRequest().getRemoteAddr();
        messageSms.setIp(ip);
        messageSms.setPhone(phone);
        messageSmsMapper.insert(messageSms);
    }


    /**
    * @Title: checkImagCode
    * @Description: 检验图形验证码是否一致
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/6 14:01
    * @Parameters:
    * @Return
    */
    private boolean checkImagCode(SmsCodeDTO dto){
        // 根据key从redis中获取到图形验证码
        String imgcode = (String)redisTemplate.opsForValue().get(dto.getImageCodeKey());
        // 比较输入的图形验证码是否正确
        if (StringUtils.equalsIgnoreCase(dto.getImageCode(), imgcode)){
            return true;
        }
        return false;
    }

    /**
    * @Title: getSmsCode
    * @Description: 获取发送的短信验证码
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/6 14:01
    * @Parameters:
    * @Return
    */
    private RedisSmsDto getSmsCode(SmsCodeDTO dto){
        // 获取key值
        String key = SmsCodeConstant.SMS_PHONE + dto.getMobile();
        // 根据key从redis中获取到
        RedisSmsDto redisSmsDto = (RedisSmsDto)redisTemplate.opsForValue().get(key);
        String code = null;
        if (redisSmsDto != null){
            long nowTime = System.currentTimeMillis();
            if (nowTime - redisSmsDto.getTime()/1000 < SmsConstant.LAST_TIME){
                throw new GlobleException("请一分钟后再试","50001");
            }
            code = redisSmsDto.getCode();
        }else {
            code = StrUtils.getRandomString(6);
        }
        return new RedisSmsDto(code,System.currentTimeMillis());
    }

    /**
    * @Title: sendPhone
    * @Description: 发送手机验证码
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/6 16:12
    * @Parameters:
    * @Return
    */
    private void sendPhone(String phone, String code){
        // 调用发送手机验证码的第三方平台提供的工具类
        // TODO 待定
        log.info("手机号为：" +phone+ "验证码为："+code);

    }
}
